﻿#include "pch.h"
#if _QG_ENABLE_WIDGET
#include "qgp/qgach.h"
#include "qgp/qgaud.h"
#include "qgp/qguwgs.h"

//////////////////////////////////////////////////////////////////////////
// 폼
KIMPL_SUBCLASS(qwForm, "WidgetForm");

//
qwForm::qwForm(qgWidgetType type/* = QGW_FORM*/)
	: super_type(type)
{
	_insts.fill = true;
	_insts.input = true;
	_insts.ctnr = true;
	_insts.sizable = true;
	_insts.movable = true;
	_insts.shadow = true;
	_insts.border = true;

	_sizer.minsize.Set(32 + 32, 32 + 24);
	_sizer.maxsize.Set(K_MAX_SHORT, K_MAX_SHORT);
}

//
qwForm::~qwForm()
{
	kobj_unload(_title.icon);
}

//
void qwForm::OnInitialize()
{
	super_type::OnInitialize();

	_sizer.res = _shed->GetResource(QGWELM_FORM_SIZER);

	_title.rico = _shed->GetResource(QGWELM_FORM_ICON);
	_title.height = _font->GetSize() > 24 ? _font->GetSize() : 24;

	_title.blend.color[1] = tpl::Color(_res[QGWELM_NORMAL].color);
	_title.blend.color[2] = tpl::Color(_res[QGWELM_NORMAL].color);

	if (_text_str.IsEmpty())
		_text_str.Format("form#%d", _id);
}

//
bool qwForm::OnUpdate(float adv)
{
	bool childrefresh;

	BuildBound();

	_bsave = _client;
	_client.top += _title.height + 4;

	if (!NeedRefresh())
		childrefresh = false;
	else
	{
		kint w = _client.Width();
		kint h = _client.Height();

		// 작업 영역 높이가 없으면 아예 그리지 않는다
		_bg.visible = !(h < 1);

		// 작업 영역 너비, 아이콘 & 기능 버튼이 표시되지 않으면 재조정
		if (w < 26 * 2)
		{
			w = 26 * 2;
			_bound.right = _bound.left + w;
			_bsave.right = _bsave.left + w;
			_client.right = _client.left + w;
		}

		// 타이틀 및 크기 조절 영역 
		_title.bound.Set(_bsave.left, _bsave.top, _bsave.right, _client.top - 1);
		_sizer.bound.Set(_client.right - 16, _client.bottom - 16, _client.right, _client.bottom);

		_text_info.anch = CalcAlign(QGWALIGN_VCENTER, tpl::Point(0, _text_info.size), _title.bound);

		//
		childrefresh = true;
		ResetRefresh();
	}

	// 딸린 애들
	kForEach(qwCtrl* w, _ctls)
	{
		if (childrefresh && !w->NeedRefresh())
			w->SetRefresh();

		if (w->CanSize() && w->HasAnchor())
		{
			// 앵커가 달려 있는데...
			// 어카지???
		}

		if (w->IsVisible() && !w->OnUpdate(adv))
			break;
	}

	// 타이틀
	_title.blend.Update(adv, _shed->GetBlendSpeed());

	return true;
}

//
void qwForm::OnDraw()
{
	if (TestChangeLayout())
	{
		// 움직이고 있으면 투명하게
		_shed->SetAlphaOverride(200);
	}

	// 배경
	if (_bg.visible)
	{
		// 배경
		if (CanFill())
		{
			if (HasShadow())
			{
				_shed->DrawFillRect(tpl::Rect(_bsave.left + 5, _bsave.bottom, _bsave.right, _bsave.bottom + 5), _color_shadow);
				_shed->DrawFillRect(tpl::Rect(_bsave.right, _bsave.top + 5, _bsave.right + 5, _bsave.bottom + 5), _color_shadow);
			}

			_shed->DrawFillRect(_client, _bg.res, _bg.tex);
		}

		// 딸린 애들...도 배경이 보여야 그림
		if (_ctls.IsHave())
		{
			// 역순으로 그림
			for (auto it = _ctls.Last();; --it)
			{
				qwCtrl* w = *it;

				if (w->IsVisible())
					w->OnDraw();

				if (it == _ctls.First())
					break;
			}
		}

		// 사이즈 표시
		if (CanSize())
		{
			_shed->DrawFillRect(_sizer.bound, _sizer.res, _tex);
		}
	}

	// 타이틀
	_shed->DrawFillRect(_title.bound, tpl::ColorValue(_title.blend.Value()));

	// 타이틀 아이콘
	if (_title.icon)
		_shed->DrawFillRect(tpl::Rect(_bsave.left + 1, _bsave.top + 1, 24, 24), _title.rico, _title.icon);

	// 타이틀 글자
	if (HasText())
		_shed->DrawAnchText(_font, _text_str.Data(), _title.bound.Deflate(24 + 1, 1, 0, 0), _text_info, 0);

	// 외곽선
	if (HasBorder())
		_shed->DrawEmptyRect(_bsave, _color_border);

	//
	_shed->SetAlphaOverride();

	qwCtrl::OnDraw();
}

//
void qwForm::OnChangeStatus(qgWidgetStatus status)
{
	_title.blend.Reset(tpl::Color(_res[status].color), tpl::Color(_title.blend.color[0]));
}

//
const qbWidgetResource& qwForm::GetResource(qgWidgetElement nth)
{
	if (nth == QGWELM_FORM_ICON)
		return _title.rico;
	else if (nth == QGWELM_FORM_SIZER)
		return _sizer.res;
	return super_type::GetResource(nth);
}

//
void qwForm::SetIcon(qgTexture* tex)
{
	if (_title.icon != tex)
	{
		kobj_unload(_title.icon);
		_title.icon = tex;
		kobj_load(tex);
	}
}

//
bool qwForm::SetResource(qgWidgetElement nth, const qbWidgetResource& res)
{
	if (nth == QGWELM_FORM_ICON)
		_title.rico = res;
	else if (nth == QGWELM_FORM_SIZER)
		_sizer.res = res;
	else
		return super_type::SetResource(nth, res);
	return true;
}

//
bool qwForm::OnMouseMove(kint x, kint y, const tpl::Point& relative, kushort state)
{
	kint n;

	if (TestMoving())
	{
		// 움직이기
		const tpl::Rect& pbound = _parent ? _parent->GetClient() : _shed->GetBound();

		// 이동 변위
		tpl::Point dt(x - _delta.x, y - _delta.y);

		if (dt.x < pbound.left)
			dt.x = pbound.left;

		if (dt.y < pbound.top)
			dt.y = pbound.top;

		// 크기 검사
		tpl::Point sz(_bound.Width() + dt.x, _bound.Height() + dt.y);

		if (sz.x > pbound.right)
		{
			n = pbound.right - sz.x;
			dt.x += n;
			sz.x += n;
		}

		if (sz.y > pbound.bottom)
		{
			n = pbound.bottom - sz.y;
			dt.y += n;
			sz.y += n;
		}

		// 바운드 재 계산
		_bound.Set(dt.x, dt.y, sz.x, sz.y);
		SetRefresh();

		if (_ecb_layout_changed)
			_ecb_layout_changed(this, _bound);

		return false;
	}

	if (TestSizing())
	{
		// 크기 변경
		const tpl::Rect& pbound = _parent ? _parent->GetClient() : _shed->GetBound();
		tpl::Point dt(K_MIN(x, pbound.right), K_MIN(y, pbound.bottom));
		tpl::Point pt(dt.x - _bound.left, dt.y - _bound.top);
		tpl::Point sz(K_CLAMP(pt.x, _sizer.minsize.x, _sizer.maxsize.x), K_CLAMP(pt.y, _sizer.minsize.y, _sizer.maxsize.y));

		_bound.right = _bound.left + sz.x;
		_bound.bottom = _bound.top + sz.y;
		SetRefresh();

		if (_ecb_layout_changed)
			_ecb_layout_changed(this, _bound);

		return false;
	}

	return super_type::OnMouseMove(x, y, relative, state);
}

//
bool qwForm::OnMouseDown(kint x, kint y, kushort button)
{
	if (button == QIM_LEFT)
	{
		// 타이틀바?
		if (CanMove() && _title.bound.OnPoint(x, y))
		{
			_insts.moving = true;

			// 여기서는 아직 움직이지 않았기 때문에 layout change 안 보냄

			_delta.Set(x - _title.bound.left, y - _title.bound.top);

			return false;
		}

		// 사이즈?
		if (CanSize() && _sizer.bound.OnPoint(x, y))
		{
			_insts.sizing = true;

			// 여기서는 아직 움직이지 않았기 때문에 layout change 안 보냄

			_delta.Set(x - _title.bound.left, y - _title.bound.top);

			return false;
		}
	}

	return super_type::OnMouseDown(x, y, button);
}

//
bool qwForm::OnMouseUp(kint x, kint y, kushort button)
{
	if (button == QIM_LEFT)
	{
		if (TestMoving())
		{
			_insts.moving = false;

			if (_ecb_layout_changed)
				_ecb_layout_changed(this, _bound);

			return true;
		}

		if (TestSizing())
		{
			_insts.sizing = false;

			if (_ecb_layout_changed)
				_ecb_layout_changed(this, _bound);

			return true;
		}
	}

	return super_type::OnMouseUp(x, y, button);
}

#endif	// _QG_ENABLE_WIDGET
